
#Clean memory
rm(list=ls())

# Importing R packages
library("Rmpi")
library("XML")

#Importing sources
source('Configuration.R')
source('Measurements.R')
source('ParametersInit.R')
source('ParametersGenerator.R')
source('SlavesFeeder.R')
source('TasksFactory.R')
source('Ldndc.R')
source('ModelUtils.R')
source('MpiMaster.R')
source('Database.R')
source('Logging.R')
source('ChainState.R')
source('GelmanRubin.R')

library(logging)


convergence <- function(results, iteration) {
  
  convergence <- FALSE
  if (iteration == 5)
    convergence <- TRUE
  
  show(iteration)
  convergence
  
}

#
#
# Get the list of tasks ids
#
#
getTasksIds <- function(chainStatesAndModels) {
  
  ids <- list()
  
  for (i in 1:length(chainStatesAndModels)) {
    
    ids[[i]] <- chainStatesAndModels[[i]]$chainState$id
    
  }
  
  ids
  
}


#Get configuration
configuration <- new("Configuration")

Logging()

paramInit <- ParametersInit()
priorProbabilityDistribution <- paramInit$priorProbabilityDistribution()
parameters <- paramInit$firstParameters(priorProbabilityDistribution)

db <- Database()
db$create(rownames(parameters))


#Factory creates tasks with chainStates and the model instances
tasksFac <- TasksFactory()
chainStatesAndModels <- tasksFac$generateTasks()

iteration <- 0

results <- NULL

measurements <<- Measurements()$readMeasurements()
feeder <- SlavesFeeder(measurements=measurements, priorProbabilityDistribution=priorProbabilityDistribution)
mpi <- MpiMaster(feeder=feeder)
gelmanRubin <- GelmanRubin(ids=getTasksIds(chainStatesAndModels))

while(!gelmanRubin$reachTheEnd()) {

  loginfo(paste("Iteration: ",iteration,sep=""))

  tasks <- chainStatesAndModels
  
  #WARNING: is very important to treat carefully the results data type.
  #Right now is a list with four lists inside. Each one have: a dataframe call parameters and a number call likelihood
  results <- mpi$executeParallelTasks(tasks)
    
  #Now we process the results Gelman Rubin process with likelihoods and parameters
  iteration <<- iteration + 1
  
  for (i in 1:length(results)) {
    
    chainState <- results[[i]]$chainState
    
    #show(chainState$candidateParameters)
    db$insertParameters(chainState$id,iteration,chainState$lastPosterior,chainState$candidateParameters)
    
    chainStatesAndModels[[i]]$chainState <- chainState
    chainStatesAndModels[[i]]$chainState$iteration <- iteration
    
    gelmanRubin$update(chainState)
  }
  
  #TODO esto irá dentro del mpiMaster
  #posteriors <- candidateApproval(likelihood, posteriors)
  #acceptanceRate <- posteriors$acceptedCount / iteration
  
  #Garbage collection
  loginfo(gc())
}

db$close()



